#pragma once

#include <string>
#include <memory>
#include <jsoncpp/json/json.h>
#include "Http.hpp"
#include "Mysql.hpp"

using namespace Http_ns;

class Task
{
private:
    Json::Value Analysis(const std::shared_ptr<Request> &req)
    {
        std::string json_string = req->Content();
        Json::Value T;
        Json::Reader reader;
        bool parsingSuccessful = reader.parse(json_string, T);
        if (!parsingSuccessful)
        {
            // 解析失败，输出错误信息
            std::cout << "Failed to parse JSON: " << reader.getFormattedErrorMessages() << std::endl;
            return Json::Value();
        }

        return T;
    }

public:
    void Login(const std::shared_ptr<Request> &req, const std::shared_ptr<Response> &resp)
    {
        // 解析Json串
        Json::Value T = Analysis(req);

        // 判断账号是否正确
        std::string id = T["username"].asString();
        std::string pswd = T["password"].asString();

        bool res = sql.SearchOne(id, pswd);

        Json::Value root;
        if (res == true)
            root["success"] = true;
        else
            root["success"] = false;

        Json::FastWriter writer;
        std::string text = writer.write(root);

        resp->AddCode(200, "OK");
        resp->AddHeader("Content-Length", std::to_string(text.size()));
        resp->AddHeader("Content-Type", "application/json");
        resp->AddHeader("Content-Type", "application/javascript; charset=UTF-8");
        resp->AddBodyText(text);
    }

    void Register(const std::shared_ptr<Request> &req, const std::shared_ptr<Response> &resp)
    {
        Json::Value T = Analysis(req);
        std::string id = T["username"].asString();
        std::string pswd = T["password"].asString();

        bool res = sql.SearchId(id);

        Json::Value root;
        if (res == true)
        {
            root["success"] = false;
        }
        else
        {
            root["success"] = true;
            sql.InsertIntoUsers(id, pswd);
        }

        Json::FastWriter writer;
        std::string text = writer.write(root);
        resp->AddCode(200, "OK");
        resp->AddHeader("Content-Length", std::to_string(text.size()));
        resp->AddHeader("Content-Type", "application/json");
        resp->AddHeader("Content-Type", "application/javascript; charset=UTF-8");
        resp->AddBodyText(text);
    }

    void Loaded(const std::shared_ptr<Request> &req, const std::shared_ptr<Response> &resp)
    {
        // 因为发送的请求只是 /students ,没有携带报文，不用解析
        std::vector<Staff> list = sql.Search();
        Json::Value jsonArray(Json::arrayValue);

        for (auto &e : list)
        {
            Json::Value root;
            e.Serialize(root);

            jsonArray.append(root);
        }
        Json::FastWriter writer;
        std::string text = writer.write(jsonArray);

        resp->AddCode(200, "OK");
        resp->AddHeader("Content-Length", std::to_string(text.size()));
        resp->AddHeader("Content-Type", "application/json");
        resp->AddHeader("Content-Type", "application/javascript; charset=UTF-8");
        resp->AddBodyText(text);
    }

    void Add(const std::shared_ptr<Request> &req, const std::shared_ptr<Response> &resp)
    {
        Json::Value T = Analysis(req);
        Staff person;
        person.DeSerialize(T);

        auto now = std::chrono::system_clock::now();
        std::time_t now_time = std::chrono::system_clock::to_time_t(now);
        std::tm *now_tm = std::localtime(&now_time);

        person.id += std::to_string(now_tm->tm_year + 1900);
        person.id += std::to_string(num);
        num++;

        // 检验数据合法性
        // To Do

        bool res = sql.InsertIntoPerson(person);
        Json::Value root;
        if (res == true)
        {
            root["success"] = true;
        }
        else
        {
            root["success"] = false;
        }

        Json::FastWriter writer;
        std::string text = writer.write(root);
        resp->AddCode(200, "OK");
        resp->AddHeader("Content-Length", std::to_string(text.size()));
        resp->AddHeader("Content-Type", "application/json");
        resp->AddHeader("Content-Type", "application/javascript; charset=UTF-8");
        resp->AddBodyText(text);
    }

    // 查询，请求中会携带两个参数
    void Search(const std::shared_ptr<Request> &req, const std::shared_ptr<Response> &resp)
    {
        std::string content = req->Content();
        auto pos = content.find("&");

        std::string str1 = content.substr(0, pos);
        std::string str2 = content.substr(pos + 1);

        auto eq1 = str1.find("=");
        auto eq2 = str2.find("=");
        std::string term = str1.substr(eq1 + 1);
        std::string keyword = str2.substr(eq2 + 1);

        if (keyword.empty())
        {
            return Loaded(req, resp);
        }

        std::vector<Staff> list = sql.Search(term, keyword);
        Json::Value jsonArray(Json::arrayValue);

        for (auto &e : list)
        {
            Json::Value root;
            e.Serialize(root);

            jsonArray.append(root);
        }
        Json::FastWriter writer;
        std::string text = writer.write(jsonArray);
        resp->AddCode(200, "OK");
        resp->AddHeader("Content-Length", std::to_string(text.size()));
        resp->AddHeader("Content-Type", "application/json");
        resp->AddHeader("Content-Type", "application/javascript; charset=UTF-8");
        resp->AddBodyText(text);
    }

    void Update(const std::shared_ptr<Request> &req, const std::shared_ptr<Response> &resp)
    {
        Json::Value T = Analysis(req);
        Staff person;
        person.DeSerialize(T["updatedData"]);
        std::cout << "test" << std::endl;

        std::string OldPersonId = T["olddata"]["id"].asString();
        bool Dres = sql.DeleteOne(OldPersonId);

        bool res = sql.InsertIntoPerson(person);
        Json::Value root;
        if (Dres == true && res == true)
        {
            root["success"] = true;
        }
        else
        {
            root["success"] = false;
        }

        Json::FastWriter writer;
        std::string text = writer.write(root);
        resp->AddCode(200, "OK");
        resp->AddHeader("Content-Length", std::to_string(text.size()));
        resp->AddHeader("Content-Type", "application/json");
        resp->AddHeader("Content-Type", "application/javascript; charset=UTF-8");
        resp->AddBodyText(text);
    }

    void Delete(const std::shared_ptr<Request> &req, const std::shared_ptr<Response> &resp)
    {
        Json::Value T = Analysis(req);
        std::string id = T["id"].asString();
        bool res = sql.DeleteOne(id);
        Json::Value root;
        if (res == true)
        {
            root["success"] = true;
        }
        else
        {
            root["success"] = false;
        }

        Json::FastWriter writer;
        std::string text = writer.write(root);
        resp->AddCode(200, "OK");
        resp->AddHeader("Content-Length", std::to_string(text.size()));
        resp->AddHeader("Content-Type", "application/json");
        resp->AddHeader("Content-Type", "application/javascript; charset=UTF-8");
        resp->AddBodyText(text);
    }

    void GetDepartment(const std::shared_ptr<Request> &req, const std::shared_ptr<Response> &resp)
    {
        std::vector<Department> list = sql.SearchDepartment();
        Json::Value jsonArray(Json::arrayValue);

        for (auto &e : list)
        {
            Json::Value root;
            e.Serialize(root);

            jsonArray.append(root);
        }
        Json::FastWriter writer;
        std::string text = writer.write(jsonArray);
        resp->AddCode(200, "OK");
        resp->AddHeader("Content-Length", std::to_string(text.size()));
        resp->AddHeader("Content-Type", "application/json");
        resp->AddHeader("Content-Type", "application/javascript; charset=UTF-8");
        resp->AddBodyText(text);
    }

    void GetPersonChange(const std::shared_ptr<Request> &req, const std::shared_ptr<Response> &resp)
    {
        std::vector<Department> list = sql.SearchDepartment();
        Json::Value jsonArray(Json::arrayValue);

        for (auto &e : list)
        {
            Json::Value root;
            e.Serialize(root);

            jsonArray.append(root);
        }
        Json::FastWriter writer;
        std::string text = writer.write(jsonArray);
        resp->AddCode(200, "OK");
        resp->AddHeader("Content-Length", std::to_string(text.size()));
        resp->AddHeader("Content-Type", "application/json");
        resp->AddHeader("Content-Type", "application/javascript; charset=UTF-8");
        resp->AddBodyText(text);
    }

    void GetPersonNel(const std::shared_ptr<Request> &req, const std::shared_ptr<Response> &resp)
    {
        std::vector<PersonNel> list = sql.SearchPersonNel();
        Json::Value jsonArray(Json::arrayValue);

        for (auto &e : list)
        {
            Json::Value root;
            e.Serialize(root);

            jsonArray.append(root);
        }
        Json::FastWriter writer;
        std::string text = writer.write(jsonArray);
        resp->AddCode(200, "OK");
        resp->AddHeader("Content-Length", std::to_string(text.size()));
        resp->AddHeader("Content-Type", "application/json");
        resp->AddHeader("Content-Type", "application/javascript; charset=UTF-8");
        resp->AddBodyText(text);
    }

private:
    Mysql sql;
    int num = 0;
};
